/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.web.common.io;

import com.inspur.edp.web.common.JITEngineConstants;
import com.inspur.edp.web.common.entity.NodeJsCommandEnum;
import com.inspur.edp.web.common.utility.OperatingSystemUtility;

/**
 * nodejs 功能汇总
 *
 * @author noah
 */
public class NodejsFunctionUtility {
    private NodejsFunctionUtility() {
    }

    /**
     * 获取node命令执行
     *
     * @param isUpgradeTool
     * @return
     */
    public static String getNodeJsCommandInServerWithOS(NodeJsCommandEnum nodeJsCommandEnum, boolean isUpgradeTool) {
        String nodeJsPath = getNodeJsPathInServer();
        String serverPath = FileUtility.getCurrentWorkPath(isUpgradeTool);
        if (OperatingSystemUtility.isWindows()) {
            nodeJsPath = FileUtility.combine(nodeJsPath, "amd64-win");
        } else {
            nodeJsPath = FileUtility.combine(nodeJsPath, "x86_64-linux", "bin");
        }
        return getNodeJsCommandWithNodeJsPath(nodeJsCommandEnum, nodeJsPath, serverPath);
    }

    /**
     * 获取node命令执行
     *
     * @param currentServerPath
     * @return
     */
    public static String getNodeJsCommandInServerWithOS(NodeJsCommandEnum nodeJsCommandEnum, String currentServerPath) {
        String nodeJsPath = getNodeJsPathInServer();
        if (OperatingSystemUtility.isWindows()) {
            nodeJsPath = FileUtility.combine(nodeJsPath, "amd64-win");
        } else if (OperatingSystemUtility.isLinux() && !OperatingSystemUtility.isMac()) {
            // 由于内置的无法支持mac  因此mac采用外置的形式
            if (nodeJsCommandEnum == NodeJsCommandEnum.Node) {
                nodeJsPath = FileUtility.combine(nodeJsPath, "x86_64-linux", "bin");
            } else {
                // 由于通过补丁安装 linux下的npm、npx是通过link执行 无法通过windows进行补丁制作，因此移除link，使用link的具体js文件进行执行
                nodeJsPath = FileUtility.combine(nodeJsPath, "x86_64-linux");
            }

            FileUtility.setPermission(nodeJsPath);
        }
        return getNodeJsCommandWithNodeJsPath(nodeJsCommandEnum, nodeJsPath, currentServerPath);
    }


    private static String getNodeJsCommandWithNodeJsPath(NodeJsCommandEnum nodeJsCommandEnum, String nodeJsPath, String currentServerPath) {
        // 如果是mac系统 那么直接使用其对应的命令
        if (OperatingSystemUtility.isMac()) {
            return nodeJsCommandEnum.commandName();
        }
        boolean hasNodePackage = FileUtility.exists(nodeJsPath);
        String nodeCommand = "node";
        // 如果是linux系统 移除link 指定npm、npx命令 且在linux环境下
        boolean needUseLinuxJs = hasNodePackage && OperatingSystemUtility.isLinux() && (nodeJsCommandEnum == NodeJsCommandEnum.Npm || nodeJsCommandEnum == NodeJsCommandEnum.Npx);
        if (needUseLinuxJs) {
            String currentNodeCommand = getNodeJsCommandInServerWithOS(NodeJsCommandEnum.Node, currentServerPath);
            String npmCommandJsName = "npm-cli.js";
            String npxCommandJsName = "npx-cli.js";
            String npmBinPath = FileUtility.combineOptional(nodeJsPath, "lib", "node_modules", "npm", "bin");
            String npmCommandJs = FileUtility.combineOptional(npmBinPath, npmCommandJsName);
            String npxCommandJs = FileUtility.combineOptional(npmBinPath, npxCommandJsName);

            if (nodeJsCommandEnum == NodeJsCommandEnum.Npm) {
                nodeCommand = currentNodeCommand + " " + npmCommandJs;
            } else {
                nodeCommand = currentNodeCommand + " " + npxCommandJs;
            }

            // 设置文件权限

            FileUtility.setPermission(currentNodeCommand);

        } else {
            String nodeCommandName = nodeJsCommandEnum.commandName();
            nodeCommand = nodeCommandName;
            if (hasNodePackage) {
                nodeCommand = FileUtility.combine(nodeJsPath, nodeCommandName);
            }
            nodeCommand = nodeCommand + " ";
        }

        FileUtility.setPermission(nodeCommand);
        return nodeCommand;
    }

    /**
     * 获取在server中执行jit命令的操作
     *
     * @param isUpgradeTool
     * @return
     */
    public static String getNgCommandInServer(boolean isUpgradeTool) {
        String nodeJsPath = getNodeJsPathInServer();
        String ngCommandFilePath = FileUtility.combine(nodeJsPath, JITEngineConstants.NgCommandRelativePath);
        if (!FileUtility.exists(ngCommandFilePath)) {
            return "ng";
        }
        String nodeCommand = getNodeJsCommandInServerWithOS(NodeJsCommandEnum.Node, isUpgradeTool);
        String ngCommand = nodeCommand + ngCommandFilePath;

        FileUtility.setPermission(ngCommand);

        return ngCommand;
    }

    /**
     * 获取nodejs路径
     * *
     *
     * @return
     */
    public static String getNodeJsPathInServer() {
        String currentServerRTPath = FileUtility.getServerRTPath();
        String nodejsPath = FileUtility.combine(currentServerRTPath, "runtime", "nodejs");

        FileUtility.setPermission(nodejsPath);

        return nodejsPath;
    }

    /**
     * 获取在server中执行jit命令的操作
     *
     * @param isUpgradeTool
     * @return
     */
    public static String getJitCommandInServer(boolean isUpgradeTool) {
        String nodeJsPath = getNodeJsPathInServer();
        String jitCommandJsPath = FileUtility.combine(nodeJsPath, JITEngineConstants.JitCommandJsRelativePath);
        if (!FileUtility.exists(jitCommandJsPath)) {
            return "jit";
        }
        String nodeCommand = getNodeJsCommandInServerWithOS(NodeJsCommandEnum.Node, isUpgradeTool);
        String jitCommand = nodeCommand + " " + jitCommandJsPath;

        FileUtility.setPermission(jitCommand);
        return jitCommand;
    }

    /**
     * 获取在server中执行tsc命令的操作
     *
     * @param isUpgradeTool
     * @return
     */
    public static NodeJsCommandResult getTscCommandInServer(boolean isUpgradeTool) {
        String nodeJsPath = getNodeJsPathInServer();
        String jitCommandJsPath = FileUtility.combine(nodeJsPath, JITEngineConstants.ServerScriptsPath, JITEngineConstants.TscCommandRelativePath);
        NodeJsCommandResult nodeJsCommandResult = new NodeJsCommandResult();
        if (!FileUtility.exists(jitCommandJsPath)) {
            nodeJsCommandResult.setNodeJsCommand("tsc");
            nodeJsCommandResult.setUseGlobal(true);
            return nodeJsCommandResult;
        }
        String nodeCommand = getNodeJsCommandInServerWithOS(NodeJsCommandEnum.Node, isUpgradeTool);
        String tscCommand = nodeCommand + " " + jitCommandJsPath;

        FileUtility.setPermission(tscCommand);
        nodeJsCommandResult.setNodeJsCommand(tscCommand);
        nodeJsCommandResult.setUseGlobal(false);
        return nodeJsCommandResult;
    }

    /**
     * 获取在server中执行rollup命令的操作
     *
     * @param isUpgradeTool
     * @return
     */
    public static NodeJsCommandResult getRollupCommandInServer(boolean isUpgradeTool) {
        String nodeJsPath = getNodeJsPathInServer();
        String rollupCommandJsPath = FileUtility.combine(nodeJsPath, JITEngineConstants.ServerScriptsPath, JITEngineConstants.RollupCommandRelativePath);
        NodeJsCommandResult nodeJsCommandResult = new NodeJsCommandResult();
        if (!FileUtility.exists(rollupCommandJsPath)) {
            nodeJsCommandResult.setNodeJsCommand("rollup");
            nodeJsCommandResult.setUseGlobal(false);
            return nodeJsCommandResult;
        }
        String nodeCommand = getNodeJsCommandInServerWithOS(NodeJsCommandEnum.Node, isUpgradeTool);
        String rollupCommand = nodeCommand + " " + rollupCommandJsPath;

        FileUtility.setPermission(rollupCommand);
        nodeJsCommandResult.setNodeJsCommand(rollupCommand);
        nodeJsCommandResult.setUseGlobal(false);
        return nodeJsCommandResult;
    }
}


